Imports Microsoft.VisualBasic
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System.Drawing.Design
Imports System.ComponentModel.Design


Namespace Phoenix.Tools
    Public Class WizardForm : Inherits System.Windows.Forms.UserControl
#Region "Class Constants and Enumerators"
        ''' <summary>
        ''' Enum configure how much buttons will be shown by wizard 
        ''' and what state buttons will have
        ''' </summary>
        <Flags()> _
        Public Enum TWizardsButtons
            None = &H0
            <Description("Enable or Disable Previous Button")> Previous = &H1
            <Description("Enable or Disable Next/Finish button")> [Next] = &H2
            <Description("If checked then Next button become a Finish Button")> Finish = &H4
            <Description("Show or not Help button")> Help = &H10
            <Description("Enable or Disable Cancel button")> Cancel = &H20
            All = Previous Or [Next] Or Cancel Or Help
            AllShort = Previous Or [Next] Or Cancel
            AllShortFinishDisabled = Previous Or Finish Or Cancel
            AllShortFinishEnabled = Previous Or [Next] Or Finish Or Cancel
            AllFinishEnabled = Previous Or [Next] Or Finish Or Cancel Or Help
            AllFinishDisabled = Previous Or Finish Or Help Or Cancel
        End Enum

        ''' <summary>
        ''' Enum configure Help Button Position
        ''' </summary>
        Public Enum THelpPosition
            AlignLeft
            AlignRight
        End Enum

        ' static constants of Text displayed on Buttons. This values can be 
        ' replaced by Wizard user in case of localization
        Public Shared DEF_FINISH As String = "&Finish"
        Public Shared DEF_NEXT As String = "&Next >"
        Public Shared DEF_BACK As String = "< &Back"
        Public Shared DEF_HELP As String = "&Help"
        Public Shared DEF_CANCEL As String = "&Cancel"
        Public Shared DEF_CLOSE As String = "Do you want to close Wizard and loose all Data entered on Wizard Pages?"
        Public Shared DEF_WARNING As String = "Warning"
#End Region

#Region "Class Internal Classes/Collection/EventArgs/Delegates"
        ''' <summary>
        ''' Class Used to sort collection items by Index property
        ''' </summary>
        Friend Class CollectionComapre : Implements IComparer
            Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
                Dim page1 As WizardPageBase = CType(x, WizardPageBase)
                Dim page2 As WizardPageBase = CType(y, WizardPageBase)

                Return IIf((page1.Index > page2.Index), 1, (IIf((page1.Index < page2.Index), -1, 0)))
            End Function
        End Class


        ''' <summary>
        ''' Custom collection which we use to work with Wizard Pages. Some
        ''' methods of IList interface are overrided to make collection 
        ''' type safe. Also Collection support "Changed" event and sorting 
        ''' by Index property.
        ''' </summary>
        Public Class WizardPagesCollection : Inherits CollectionBase
#Region "Class Members"
            Private m_parent As WizardForm
#End Region

#Region "Class events"
            Public Event Changed As EventHandler
#End Region

#Region "Class Initialize methods"
            Public Sub New(ByVal parent As WizardForm)
                m_parent = parent
            End Sub
#End Region

#Region "IList interface implementation"
            Public Function Add(ByVal value As WizardPageBase) As Integer
                If Contains(value) = True Then
                    Return IndexOf(value)
                End If

                value.WizardPageParent = m_parent
                Dim index As Integer = InnerList.Add(value)

                If value.Index < 0 Then
                    value.Index = index
                End If

                RaiseChanged(value)

                Return index
            End Function

            Public Sub AddRange(ByVal array As WizardPageBase())
                For Each page As WizardPageBase In array
                    Add(page)
                Next page
            End Sub

            Public Function Contains(ByVal value As WizardPageBase) As Boolean
                Return InnerList.Contains(value)
            End Function

            Public Function IndexOf(ByVal value As WizardPageBase) As Integer
                Return InnerList.IndexOf(value)
            End Function

            Public Sub Insert(ByVal index As Integer, ByVal value As WizardPageBase)
                value.WizardPageParent = m_parent
                InnerList.Insert(index, value)

                If value.Index < 0 Then
                    value.Index = index
                End If

                RaiseChanged(value)
            End Sub

            Public Sub Remove(ByVal value As WizardPageBase)
                InnerList.Remove(value)
                RaiseChanged()
            End Sub
#End Region

#Region "IList Properties"
            Default Public Property Item(ByVal index As Integer) As WizardPageBase
                Get
                    Return CType(IIf(TypeOf InnerList(index) Is WizardPageBase, InnerList(index), Nothing), WizardPageBase)
                End Get
                Set(ByVal Value As WizardPageBase)
                    Value.WizardPageParent = m_parent
                    Value.Index = index
                    InnerList(index) = Value
                    RaiseChanged(Value)
                End Set
            End Property
#End Region

#Region "Class Helper methods"
            Protected Sub RaiseChanged(ByVal value As WizardPageBase)
                If Not ChangedEvent Is Nothing Then
                    RaiseEvent Changed(value, EventArgs.Empty)
                End If
            End Sub

            Protected Sub RaiseChanged()
                If Not ChangedEvent Is Nothing Then
                    RaiseEvent Changed(Me, EventArgs.Empty)
                End If
            End Sub

            Public Sub Sort()
                InnerList.Sort(New CollectionComapre)
            End Sub
#End Region

#Region "Class overrides"
            Protected Overrides Sub OnClearComplete()
                ' raise Changed Event when collection cleared
                RaiseChanged()
            End Sub

            Protected Overrides Sub OnSetComplete(ByVal index As Integer, ByVal oldValue As Object, ByVal newValue As Object)
                Dim page As WizardPageBase = CType(newValue, WizardPageBase)
                page.WizardPageParent = m_parent
                If page.Index < 0 Then
                    page.Index = index
                End If

                MyBase.OnSetComplete(index, oldValue, page)

                RaiseChanged(page)
            End Sub

            Protected Overrides Sub OnInsertComplete(ByVal index As Integer, ByVal value As Object)
                Dim page As WizardPageBase = CType(value, WizardPageBase)
                page.WizardPageParent = m_parent
                If page.Index < 0 Then
                    page.Index = index
                End If

                MyBase.OnInsertComplete(index, page)

                RaiseChanged(page)
            End Sub

            Protected Overrides Sub OnRemoveComplete(ByVal index As Integer, ByVal value As Object)
                RaiseChanged()
            End Sub
#End Region
        End Class

        ''' <summary>
        ''' Special Parameters send to user on Cancel Event
        ''' </summary>
        Public Class EventWizardCancelArgs : Inherits EventArgs
            Private m_strMessage As String
            Private m_strTitle As String

            Public Property Message() As String
                Get
                    Return m_strMessage
                End Get
                Set(ByVal Value As String)
                    m_strMessage = Value
                End Set
            End Property

            Public Property Title() As String
                Get
                    Return m_strTitle
                End Get
                Set(ByVal Value As String)
                    m_strTitle = Value
                End Set
            End Property

            ' hide default constructor
            Private Sub New()
            End Sub

            'INSTANT VB NOTE: The parameter title was renamed since Visual Basic will not uniquely identify class members when parameters have the same name:
            'INSTANT VB NOTE: The parameter message was renamed since Visual Basic will not uniquely identify class members when parameters have the same name:
            Public Sub New(ByVal title_Renamed As String, ByVal message_Renamed As String)
                MyBase.New()
                m_strTitle = title_Renamed
                m_strMessage = message_Renamed
            End Sub
        End Class

        ''' <summary>
        ''' Event parameters by which usr can control logic of page show
        ''' </summary>
        Public Class EventNextArgs : Inherits EventArgs
            Private m_page As WizardPageBase
            Private m_iStep As Integer = 1

            Public ReadOnly Property CurrentPage() As WizardPageBase
                Get
                    Return m_page
                End Get
            End Property

            Public Property [Step]() As Integer
                Get
                    Return m_iStep
                End Get
                Set(ByVal Value As Integer)
                    m_iStep = Value
                End Set
            End Property

            Private Sub New()
            End Sub

            Public Sub New(ByVal page As WizardPageBase)
                m_page = page
            End Sub

            'TODO: INSTANT VB TODO TASK: step is a keyword in VB.NET. Change the name or use square brackets to override it:
            'INSTANT VB NOTE: The parameter step was renamed since Visual Basic will not uniquely identify class members when parameters have the same name:
            Public Sub New(ByVal page As WizardPageBase, ByVal step_Renamed As Integer)
                Me.New(page)
                m_iStep = step_Renamed
            End Sub
        End Class


        Public Delegate Sub WizardCancelEventHandler(ByVal sender As Object, ByVal e As EventWizardCancelArgs)
        Public Delegate Sub WizardNextEventHandler(ByVal sender As Object, ByVal e As EventNextArgs)
#End Region

#Region "Class Members"
        Private m_eButtons As TWizardsButtons = TWizardsButtons.All ' wizard buttons
        Private m_eHelpPosition As THelpPosition = THelpPosition.AlignLeft ' wizard Help Button state

        Private m_bFireEvents As Boolean = True ' QUIET Mode indicator
        Private m_bShowConfirm As Boolean = True ' Does control show Confirmation Message on Cancel press
        Private m_bFinishCalled As Boolean ' indeicate is Finish event was called or not
        Private m_bCancelCalled As Boolean ' indeicate is Cancel event was called or not

        Private m_pages As WizardPagesCollection ' Wizard Pages Collection
        Private m_iShowIndex As Integer = 0 ' Index of Shown Wizard page
        Private m_iLastShown As Integer = -1
        Private m_CurrentPage As WizardPageBase ' Currently Shown Wizard Page
#End Region

#Region "Form controls"
        Private pnlHeader As System.Windows.Forms.Panel
        Private imgHeader As System.Windows.Forms.PictureBox
        Private lblTitle As System.Windows.Forms.Label
        Private lblDescription As System.Windows.Forms.Label
        Private pnlBody As System.Windows.Forms.Panel
        Private WithEvents btnCancel As System.Windows.Forms.Button
        Private WithEvents btnNextFinish As System.Windows.Forms.Button
        Private WithEvents btnBack As System.Windows.Forms.Button
        Private WithEvents btnHelp As System.Windows.Forms.Button
        Private pnlMain As System.Windows.Forms.Panel
        Private lineDownLimit As Phoenix.Tools.LineFrame

        Private components As System.ComponentModel.Container = Nothing
#End Region

#Region "Class Events"
        <Category("Property Changed")> _
        Public Event WizardButtonsChanged As EventHandler

        <Category("Property Changed")> _
        Public Event HelpAlignChanged As EventHandler

        'TODO: INSTANT VB TODO TASK: Next is a keyword in VB.NET. Change the name or use square brackets to override it:
        <Category("Wizard")> _
        Public Event NextEvent As WizardNextEventHandler

        <Category("Wizard")> _
        Public Event Finish As WizardNextEventHandler

        <Category("Wizard")> _
        Public Event Back As WizardNextEventHandler

        <Category("Wizard")> _
        Public Event Cancel As WizardCancelEventHandler

        <Category("Wizard")> _
        Public Event PageShown As WizardNextEventHandler

        <Category("Wizard")> _
        Public Event Help As EventHandler

        <Category("Wizard")> _
        Public Event WizardClosed As EventHandler
#End Region

#Region "Class Properties"
        <Browsable(True), Category("Wizard"), Description("Gets/Sets buttons states in wizard control for current Wizard Page"), DefaultValue(GetType(WizardForm.TWizardsButtons), "All"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Editor("UtilityLibrary.Designers.FlagsEditor, UtilityLibrary.Designers, Version=1.0.4.0, Culture=neutral, PublicKeyToken=fe06e967d3cf723d", GetType(UITypeEditor))> _
        Public Property WizardButtons() As TWizardsButtons
            Get
                Return m_eButtons
            End Get
            Set(ByVal Value As TWizardsButtons)
                If Value <> m_eButtons Then
                    m_eButtons = Value
                    OnWizardButtonChanged()
                End If
            End Set
        End Property

        <Browsable(True), Category("Wizard"), Description("Gets/Sets Help button align on wizard Control"), DefaultValue(GetType(WizardForm.THelpPosition), "AlignLeft"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public Property HelpAlign() As THelpPosition
            Get
                Return m_eHelpPosition
            End Get
            Set(ByVal Value As THelpPosition)
                If Value <> m_eHelpPosition Then
                    m_eHelpPosition = Value
                    OnHelpAlignChanged()
                End If
            End Set
        End Property

        <Browsable(True), Category("Wizard"), Description("Gets collection of wizard pages"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public ReadOnly Property Pages() As WizardPagesCollection
            Get
                Return m_pages
            End Get
        End Property

        <Browsable(False), Description("Gets/Sets QUIET Mode of control"), DefaultValue(False)> _
        Public Property QuietMode() As Boolean
            Get
                Return Not m_bFireEvents
            End Get
            Set(ByVal Value As Boolean)
                m_bFireEvents = Not Value
            End Set
        End Property

        <Browsable(True), Category("Wizard"), Description("Gets/Sets Does Wizard Show confirmation dialog on Cancel button Press"), DefaultValue(True)> _
        Public Property ShowCancelConfirm() As Boolean
            Get
                Return m_bShowConfirm
            End Get
            Set(ByVal Value As Boolean)
                m_bShowConfirm = Value
            End Set
        End Property

        <Browsable(True), Category("Wizard"), Description("Gets/Sets Current page of wizard")> _
        Public Property PageIndex() As Integer
            Get
                Return m_iShowIndex
            End Get
            Set(ByVal Value As Integer)
                If Value <> m_iShowIndex AndAlso Value < m_pages.Count AndAlso Value >= 0 Then
                    m_iShowIndex = Value
                    ShowWizardPage()
                End If
            End Set
        End Property
#End Region

#Region "Class Initialize/Finilize methods"
        ''' <summary>
        ''' Default Constructor
        ''' </summary>
        Public Sub New()
            InitializeComponent()

            m_pages = New WizardPagesCollection(Me)
            AddHandler m_pages.Changed, AddressOf PagesCollectionChanged

            btnBack.Text = DEF_BACK
            btnHelp.Text = DEF_HELP
            btnNextFinish.Text = DEF_NEXT
            btnCancel.Text = DEF_CANCEL
        End Sub

        ''' <summary>
        ''' Custom resources cleaning
        ''' </summary>
        ''' <param name="disposing"></param>
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing AndAlso Not components Is Nothing Then
                components.Dispose()
            End If

            MyBase.Dispose(disposing)
        End Sub
#End Region

#Region "Windows Form Designer generated code"
        ''' <summary>
        ''' Control Initialization and Designer View Code
        ''' </summary>
        Private Sub InitializeComponent()
            Me.btnCancel = New System.Windows.Forms.Button
            Me.pnlHeader = New System.Windows.Forms.Panel
            Me.lblTitle = New System.Windows.Forms.Label
            Me.lblDescription = New System.Windows.Forms.Label
            Me.imgHeader = New System.Windows.Forms.PictureBox
            Me.btnNextFinish = New System.Windows.Forms.Button
            Me.btnBack = New System.Windows.Forms.Button
            Me.pnlBody = New System.Windows.Forms.Panel
            Me.btnHelp = New System.Windows.Forms.Button
            Me.pnlMain = New System.Windows.Forms.Panel
            Me.lineDownLimit = New Phoenix.Tools.LineFrame
            Me.pnlHeader.SuspendLayout()
            Me.pnlMain.SuspendLayout()
            Me.SuspendLayout()
            '
            'btnCancel
            '
            Me.btnCancel.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.System
            Me.btnCancel.Location = New System.Drawing.Point(416, 338)
            Me.btnCancel.Name = "btnCancel"
            Me.btnCancel.Size = New System.Drawing.Size(76, 24)
            Me.btnCancel.TabIndex = 4
            Me.btnCancel.Text = "&Cancel"
            '
            'pnlHeader
            '
            Me.pnlHeader.BackColor = System.Drawing.Color.White
            Me.pnlHeader.Controls.Add(Me.lblTitle)
            Me.pnlHeader.Controls.Add(Me.lblDescription)
            Me.pnlHeader.Controls.Add(Me.imgHeader)
            Me.pnlHeader.Dock = System.Windows.Forms.DockStyle.Top
            Me.pnlHeader.Location = New System.Drawing.Point(0, 0)
            Me.pnlHeader.Name = "pnlHeader"
            Me.pnlHeader.Size = New System.Drawing.Size(496, 56)
            Me.pnlHeader.TabIndex = 0
            '
            'lblTitle
            '
            Me.lblTitle.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
                        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.lblTitle.FlatStyle = System.Windows.Forms.FlatStyle.System
            Me.lblTitle.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(204, Byte))
            Me.lblTitle.Location = New System.Drawing.Point(8, 8)
            Me.lblTitle.Name = "lblTitle"
            Me.lblTitle.Size = New System.Drawing.Size(432, 16)
            Me.lblTitle.TabIndex = 0
            Me.lblTitle.Text = "Wizard Page Title"
            Me.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
            '
            'lblDescription
            '
            Me.lblDescription.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
                        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.lblDescription.FlatStyle = System.Windows.Forms.FlatStyle.System
            Me.lblDescription.Location = New System.Drawing.Point(32, 22)
            Me.lblDescription.Name = "lblDescription"
            Me.lblDescription.Size = New System.Drawing.Size(408, 30)
            Me.lblDescription.TabIndex = 1
            Me.lblDescription.Text = "Description of wizard page"
            '
            'imgHeader
            '
            Me.imgHeader.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.imgHeader.Location = New System.Drawing.Point(448, 8)
            Me.imgHeader.Name = "imgHeader"
            Me.imgHeader.Size = New System.Drawing.Size(40, 40)
            Me.imgHeader.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage
            Me.imgHeader.TabIndex = 0
            Me.imgHeader.TabStop = False
            '
            'btnNextFinish
            '
            Me.btnNextFinish.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.btnNextFinish.BackColor = System.Drawing.SystemColors.Control
            Me.btnNextFinish.Cursor = System.Windows.Forms.Cursors.Default
            Me.btnNextFinish.FlatStyle = System.Windows.Forms.FlatStyle.System
            Me.btnNextFinish.Location = New System.Drawing.Point(328, 338)
            Me.btnNextFinish.Name = "btnNextFinish"
            Me.btnNextFinish.Size = New System.Drawing.Size(76, 24)
            Me.btnNextFinish.TabIndex = 0
            Me.btnNextFinish.Text = "&Next >"
            '
            'btnBack
            '
            Me.btnBack.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.btnBack.FlatStyle = System.Windows.Forms.FlatStyle.System
            Me.btnBack.Location = New System.Drawing.Point(252, 338)
            Me.btnBack.Name = "btnBack"
            Me.btnBack.Size = New System.Drawing.Size(76, 24)
            Me.btnBack.TabIndex = 1
            Me.btnBack.Text = "< &Back"
            '
            'pnlBody
            '
            Me.pnlBody.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                        Or System.Windows.Forms.AnchorStyles.Left) _
                        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.pnlBody.Location = New System.Drawing.Point(8, 64)
            Me.pnlBody.Name = "pnlBody"
            Me.pnlBody.Size = New System.Drawing.Size(480, 261)
            Me.pnlBody.TabIndex = 5
            Me.pnlBody.TabStop = True
            '
            'btnHelp
            '
            Me.btnHelp.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
            Me.btnHelp.FlatStyle = System.Windows.Forms.FlatStyle.System
            Me.btnHelp.Location = New System.Drawing.Point(8, 338)
            Me.btnHelp.Name = "btnHelp"
            Me.btnHelp.Size = New System.Drawing.Size(76, 24)
            Me.btnHelp.TabIndex = 3
            Me.btnHelp.Text = "&Help"
            '
            'pnlMain
            '
            Me.pnlMain.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                        Or System.Windows.Forms.AnchorStyles.Left) _
                        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.pnlMain.Controls.Add(Me.pnlBody)
            Me.pnlMain.Controls.Add(Me.pnlHeader)
            Me.pnlMain.Location = New System.Drawing.Point(0, 0)
            Me.pnlMain.Name = "pnlMain"
            Me.pnlMain.Size = New System.Drawing.Size(496, 325)
            Me.pnlMain.TabIndex = 0
            '
            'lineDownLimit
            '
            Me.lineDownLimit.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _
                        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.lineDownLimit.Location = New System.Drawing.Point(0, 325)
            Me.lineDownLimit.Name = "lineDownLimit"
            Me.lineDownLimit.Size = New System.Drawing.Size(496, 4)
            Me.lineDownLimit.TabIndex = 0
            Me.lineDownLimit.TabStop = False
            Me.lineDownLimit.Text = "lineFrame1"
            '
            'WizardForm
            '
            Me.Controls.Add(Me.pnlMain)
            Me.Controls.Add(Me.lineDownLimit)
            Me.Controls.Add(Me.btnBack)
            Me.Controls.Add(Me.btnNextFinish)
            Me.Controls.Add(Me.btnCancel)
            Me.Controls.Add(Me.btnHelp)
            Me.Name = "WizardForm"
            Me.Size = New System.Drawing.Size(496, 372)
            Me.pnlHeader.ResumeLayout(False)
            Me.pnlMain.ResumeLayout(False)
            Me.ResumeLayout(False)

        End Sub
#End Region

#Region "Class Helper Methods"
        ''' <summary>
        ''' Show Wizard Page. m_iShowIndex is identifier of page which 
        ''' Wizard control must show
        ''' </summary>
        Protected Sub ShowWizardPage()
            ' do not show one page twice
            If m_iShowIndex = m_iLastShown Then
                Return
            End If

            pnlMain.SuspendLayout()
            pnlBody.SuspendLayout()

            pnlMain.Controls.Clear()
            pnlBody.Controls.Clear()

            ' check if control has any pages
            If m_pages.Count > 0 Then
                m_pages.Sort()

                ' check m_iShowIndex
                If m_iShowIndex < 0 Then
                    m_iShowIndex = 0
                End If
                If m_iShowIndex >= m_pages.Count Then
                    m_iShowIndex = m_pages.Count - 1
                End If

                'TODO: INSTANT VB TODO TASK: Assignments within expressions are not supported in VB.NET
                m_iLastShown = m_iShowIndex
                m_CurrentPage = m_pages(m_iLastShown)

                ' set page parent correctly in case when is something wrong
                If Not m_CurrentPage.WizardPageParent Is Me Then
                    m_CurrentPage.WizardPageParent = Me
                End If

                ' show page custom data
                If Not m_CurrentPage.HeaderImage Is Nothing Then
                    imgHeader.Image = m_CurrentPage.HeaderImage
                Else
                    If Not m_CurrentPage.ImageList Is Nothing AndAlso m_CurrentPage.ImageIndex >= 0 AndAlso m_CurrentPage.ImageIndex < m_CurrentPage.ImageList.Images.Count Then
                        imgHeader.Image = m_CurrentPage.ImageList.Images(m_CurrentPage.ImageIndex)
                    Else
                        imgHeader.Image = Nothing
                    End If
                End If

                lblTitle.Text = m_CurrentPage.Title
                lblDescription.Text = m_CurrentPage.Description

                AddHandler m_CurrentPage.Changed, AddressOf WizardPageAttributesChanged

                ' if Welcome page then link it ot pnlMain otherwise to pnlBody
                If m_CurrentPage.WelcomePage = False Then
                    pnlMain.Controls.AddRange(New System.Windows.Forms.Control() {pnlBody, pnlHeader})

                    ' fix width and height of body panel
                    pnlBody.Width = pnlMain.Width - 16
                    pnlBody.Height = pnlMain.Height - pnlHeader.Height - 8

                    ' fix page control resize
                    If m_CurrentPage.Width <> pnlBody.Width OrElse m_CurrentPage.Height <> pnlBody.Height Then
                        m_CurrentPage.Width = pnlBody.Width
                        m_CurrentPage.Height = pnlBody.Height
                    End If

                    pnlBody.Controls.Add(m_CurrentPage)
                    pnlBody.Controls(0).Focus()
                Else
                    ' fix page control resize
                    If m_CurrentPage.Width <> pnlMain.Width OrElse m_CurrentPage.Height <> pnlMain.Height Then
                        m_CurrentPage.Size = pnlMain.Size
                    End If

                    pnlMain.Controls.Add(m_CurrentPage)
                    pnlMain.Controls(0).Focus()
                End If

                ' if current page has indicator that it is a Finish Page then Show 
                ' Finish Button
                If m_CurrentPage.FinishPage = True Then
                    m_eButtons = m_eButtons Or TWizardsButtons.Finish
                Else ' otherwise do not show Finish Button
                    m_eButtons = m_eButtons And ((Not TWizardsButtons.Finish))
                End If

                ' modify buttons states
                ChangeButtonsStates()
            Else ' in case of empty Collection show standard "work page" view of control
                pnlMain.Controls.AddRange(New System.Windows.Forms.Control() {pnlBody, pnlHeader})
            End If

            pnlBody.ResumeLayout()
            pnlMain.ResumeLayout()

            OnPageShown()
        End Sub

        ''' <summary>
        ''' According to a state of control change Buttons states and position
        ''' </summary>
        Protected Sub ChangeButtonsStates()
            Dim yPos As Integer = btnNextFinish.Top
            Dim iNewWidth As Integer = Width

            Dim bHelp As Boolean = ((m_eButtons And TWizardsButtons.Help) = TWizardsButtons.Help)
            Dim bCancel As Boolean = ((m_eButtons And TWizardsButtons.Cancel) = TWizardsButtons.Cancel)
            Dim bNext As Boolean = ((m_eButtons And TWizardsButtons.Next) = TWizardsButtons.Next)
            Dim bPrev As Boolean = ((m_eButtons And TWizardsButtons.Previous) = TWizardsButtons.Previous)
            Dim bFinish As Boolean = ((m_eButtons And TWizardsButtons.Finish) = TWizardsButtons.Finish)

            ' if we have Help Button
            btnHelp.Visible = bHelp
            btnHelp.Enabled = bHelp

            If bHelp Then
                If m_eHelpPosition = THelpPosition.AlignLeft Then ' help button on default position
                    btnHelp.Left = 8
                    btnHelp.Top = yPos

                    btnHelp.Anchor = AnchorStyles.Left Or AnchorStyles.Bottom
                Else
                    btnHelp.Left = Width - btnHelp.Width - 8
                    iNewWidth = btnHelp.Left

                    btnHelp.Anchor = AnchorStyles.Right Or AnchorStyles.Bottom
                End If

                If Not m_CurrentPage Is Nothing Then
                    btnHelp.Enabled = m_CurrentPage.HelpAvailable
                End If
            End If

            ' Cancel Button
            btnCancel.Left = iNewWidth - btnCancel.Width - 8
            btnCancel.Top = yPos
            btnCancel.Enabled = bCancel
            iNewWidth = btnCancel.Left

            ' Next or Finish Button
            btnNextFinish.Left = iNewWidth - btnNextFinish.Width - 8
            btnNextFinish.Top = yPos
            btnNextFinish.Enabled = bNext
            btnNextFinish.Text = IIf((bFinish = True), DEF_FINISH, DEF_NEXT)
            btnNextFinish.DialogResult = IIf((bFinish = True), DialogResult.OK, DialogResult.None)
            iNewWidth = btnNextFinish.Left

            ' Back button
            btnBack.Left = iNewWidth - btnBack.Width
            btnBack.Top = yPos
            btnBack.Enabled = bPrev

            If Not m_CurrentPage Is Nothing Then
                If m_CurrentPage.Index = 0 AndAlso btnBack.Enabled = True Then
                    btnBack.Enabled = False
                End If
            End If
        End Sub
#End Region

#Region "Designer Helper functions"
        ''' <summary>
        ''' Special Method Used only In Designer Control Mode
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Friend Sub WizardPageAttributesChanged(ByVal sender As Object, ByVal e As EventArgs)
            Dim page As WizardPageBase = CType(sender, WizardPageBase)

            ' remove designer event first
            RemoveHandler page.Changed, AddressOf WizardPageAttributesChanged

            m_iLastShown = -1
            ShowWizardPage()
        End Sub

        ''' <summary>
        ''' Method Indicate is Point on "Back" or "Next" Buttons. Method used only by Designer
        ''' </summary>
        ''' <param name="p">Point coordinates to check</param>
        ''' <returns>TRUE - poin found on Butons</returns>
        Public Function OnDesignedWizardButtons(ByVal p As Point) As Boolean
            Dim rect1 As Rectangle = New Rectangle(btnNextFinish.Location, btnNextFinish.Size)
            Dim rect2 As Rectangle = New Rectangle(btnBack.Location, btnBack.Size)

            Return (rect1.Contains(p) OrElse rect2.Contains(p))
        End Function

        Public Function GetCurrentPageRect() As Rectangle
            If Not m_CurrentPage Is Nothing Then
                If m_CurrentPage.WelcomePage = True Then
                    Return pnlMain.ClientRectangle
                Else
                    Return pnlBody.ClientRectangle
                End If
            End If

            Return Rectangle.Empty
        End Function
#End Region

#Region "Class Public Methods"
        ''' <summary>
        ''' Set Next Wizard Page
        ''' </summary>
        Public Sub MoveNextStep()
            m_iShowIndex += 1
            ShowWizardPage()
        End Sub

        ''' <summary>
        ''' Set Pervious Wizard Page
        ''' </summary>
        Public Sub MoveBackStep()
            m_iShowIndex -= 1
            ShowWizardPage()
        End Sub

        ''' <summary>
        ''' Step Forward in Wizard on N pages
        ''' </summary>
        ''' <param name="count">Number of pages which must be skipped</param>
        Public Sub StepNext(ByVal count As Integer)
            If count = 0 Then
                Return
            End If
            m_iShowIndex += count
            ShowWizardPage()
        End Sub

        ''' <summary>
        ''' Step in Back direction on N pages 
        ''' </summary>
        ''' <param name="count">Number of pages which must be skipped</param>
        Public Sub StepBack(ByVal count As Integer)
            If count = 0 Then
                Return
            End If
            m_iShowIndex -= count
            ShowWizardPage()
        End Sub
#End Region

#Region "Class Overrides"
        ''' <summary>
        ''' Function detach and then Attach keyPress event to all wizard pages controls 
        ''' </summary>
        Protected Sub AttachControlEvents(ByVal sender As Object, ByVal e As ControlEventArgs)
            AddHandler e.Control.KeyDown, AddressOf WizardForm_KeyDown
        End Sub

        Protected Sub DetachControlEvents(ByVal sender As Object, ByVal e As ControlEventArgs)
            RemoveHandler e.Control.KeyDown, AddressOf WizardForm_KeyDown
        End Sub

        ''' <summary>
        ''' Event Handler which raised on Pages Collection changes
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Protected Overridable Sub PagesCollectionChanged(ByVal sender As Object, ByVal e As EventArgs)
            If m_pages.Count > 0 Then
                If TypeOf sender Is WizardPageBase Then
                    Dim page As WizardPageBase = CType(sender, WizardPageBase)

                    ' remove old handlers
                    RemoveHandler page.ControlAdded, AddressOf AttachControlEvents
                    RemoveHandler page.ControlRemoved, AddressOf DetachControlEvents

                    ' add them again
                    AddHandler page.ControlAdded, AddressOf AttachControlEvents
                    AddHandler page.ControlRemoved, AddressOf DetachControlEvents
                End If

                m_iLastShown = -1
                ShowWizardPage()
            End If
        End Sub

        ''' <summary>
        ''' Method Raise "WizardButtonChanged" event
        ''' </summary>
        Protected Overridable Sub OnWizardButtonChanged()
            If m_bFireEvents = True Then
                RaiseEvent WizardButtonsChanged(Me, EventArgs.Empty)
            End If

            ChangeButtonsStates()
        End Sub

        ''' <summary>
        ''' Method Raise "HelpAlignChanged" event
        ''' </summary>
        Protected Overridable Sub OnHelpAlignChanged()
            If m_bFireEvents = True Then
                RaiseEvent HelpAlignChanged(Me, EventArgs.Empty)
            End If

            ChangeButtonsStates()
        End Sub

        ''' <summary>
        ''' Method Raise "Next" event and then Set Wizard Control to Next Page.
        ''' </summary>
        Protected Overridable Sub OnNextPressed()
            Dim e As EventNextArgs = New EventNextArgs(m_CurrentPage)

            If m_bFireEvents = True Then
                m_CurrentPage.OnNextPressed()
                RaiseEvent NextEvent(m_CurrentPage, e)
            End If

            StepNext(e.Step)
        End Sub

        ''' <summary>
        ''' Method Raise "Finish" event. Event Raised when user press Finish Button.
        ''' </summary>
        Protected Overridable Sub OnFinishPressed()
            Dim e As EventNextArgs = New EventNextArgs(m_CurrentPage)

            If m_bFireEvents = True Then
                m_bFinishCalled = True
                RaiseEvent Finish(m_CurrentPage, e)
            End If
        End Sub

        ''' <summary>
        ''' Method Raise "Back" event and then change Wizard control page to Previous Page
        ''' </summary>
        Protected Overridable Sub OnBackPressed()
            Dim e As EventNextArgs = New EventNextArgs(m_CurrentPage)

            If m_bFireEvents = True Then
                RaiseEvent Back(m_CurrentPage, e)
            End If
            StepBack(e.Step)
        End Sub

        ''' <summary>
        ''' Method Raise "Cancel" event and then if property ShowConfirm is set, show
        ''' Confirmation Dialog. If user Choose Yes on Confirmation then "WizardClosed"
        ''' event thrown to user. In Event Handler user can chage message and title of 
        ''' Confirmation Message Box. 
        ''' </summary>
        Protected Friend Overridable Function OnCancelPressed() As DialogResult
            Dim e As EventWizardCancelArgs = New EventWizardCancelArgs(DEF_WARNING, DEF_CLOSE)

            If m_bFireEvents = True Then
                RaiseEvent Cancel(Me, e)
            End If

            If m_bShowConfirm = True Then
                Dim result As DialogResult = MessageBox.Show(Me, e.Message, e.Title, MessageBoxButtons.YesNo)

                If result = DialogResult.Yes Then
                    m_bCancelCalled = True
                    OnWizardClosed()
                    Return DialogResult.Yes
                End If
            End If

            Return DialogResult.No
        End Function

        ''' <summary>
        ''' Raise "Help" event when User press Help button
        ''' </summary>
        Protected Overridable Sub OnHelpPressed()
            If m_bFireEvents = True Then
                RaiseEvent Help(m_CurrentPage, EventArgs.Empty)
            End If
        End Sub

        ''' <summary>
        ''' Raise "WizardClosed" event.
        ''' </summary>
        Protected Overridable Sub OnWizardClosed()
            If m_bFireEvents = True Then
                RaiseEvent WizardClosed(m_CurrentPage, EventArgs.Empty)
            End If
        End Sub
        ''' <summary>
        ''' Raise "PageShown" event.
        ''' </summary>
        Protected Overridable Sub OnPageShown()
            Dim e As EventNextArgs = New EventNextArgs(m_CurrentPage, m_pages.IndexOf(m_CurrentPage))

            If m_bFireEvents = True Then
                RaiseEvent PageShown(m_CurrentPage, e)
            End If
        End Sub
#End Region

#Region "Class Events Handlers"
        Private Sub btnCancel_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnCancel.Click
            If btnCancel.Visible = True AndAlso btnCancel.Enabled = True Then
                OnCancelPressed()
            End If
        End Sub

        Private Sub btnNextFinish_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnNextFinish.Click
            If btnNextFinish.Visible = True AndAlso btnNextFinish.Enabled = True Then
                If Not m_CurrentPage Is Nothing Then
                    If m_CurrentPage.FinishPage = True AndAlso DesignMode = False Then
                        OnFinishPressed()
                    Else
                        OnNextPressed()
                    End If
                Else
                    btnNextFinish.Enabled = False
                End If
            End If
        End Sub

        Private Sub btnBack_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnBack.Click
            If btnBack.Visible = True AndAlso btnBack.Enabled = True Then
                OnBackPressed()
            End If
        End Sub

        Private Sub btnHelp_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnHelp.Click
            If btnHelp.Visible = True AndAlso btnHelp.Enabled = True Then
                OnHelpPressed()
            End If
        End Sub

        Private Sub WizardForm_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles btnCancel.KeyDown
            If (e.Modifiers And Keys.Alt) = Keys.Alt Then
                If e.KeyCode = Keys.N AndAlso btnNextFinish.Enabled = True Then
                    btnNextFinish.Focus()
                ElseIf e.KeyCode = Keys.B AndAlso btnBack.Enabled = True Then
                    btnBack.Focus()
                ElseIf e.KeyCode = Keys.C AndAlso btnCancel.Enabled = True Then
                    btnCancel.Focus()
                ElseIf e.KeyCode = Keys.H AndAlso btnHelp.Enabled = True Then
                    btnHelp.Focus()
                End If
            End If

            If (e.Modifiers And (Keys.Alt Or Keys.Shift Or Keys.Control)) = 0 Then
                If e.KeyCode = Keys.Escape Then
                    If TypeOf sender Is ComboBox = True AndAlso True = (CType(sender, ComboBox)).DroppedDown Then
                        Return
                    End If

                    btnCancel_Click(sender, e)
                ElseIf e.KeyCode = Keys.Enter Then
                    If sender.Equals(btnCancel) Then
                        btnCancel_Click(sender, e)
                    ElseIf sender.Equals(btnBack) Then
                        btnBack_Click(sender, e)
                    ElseIf sender.Equals(btnHelp) Then
                        btnHelp_Click(sender, e)
                    ElseIf TypeOf sender Is TextBoxBase = True Then  ' skip enter key for multiline controls
                        Dim ctrl As TextBoxBase = CType(sender, TextBoxBase)

                        If ctrl.Multiline = False Then
                            btnNextFinish_Click(sender, e)
                        End If
                    ElseIf TypeOf sender Is ComboBox = True Then
                        Dim box As ComboBox = CType(sender, ComboBox)

                        If False = box.DroppedDown Then
                            btnNextFinish_Click(sender, e)
                        End If
                    Else
                        btnNextFinish_Click(sender, e)
                    End If
                End If
            End If
        End Sub

        Private Sub WizardForm_Closing(ByVal sender As Object, ByVal e As CancelEventArgs)
            ''' if user press Finish Button and in Finish event handler user 
            ''' call Close() method, we must accept closing without any questions.
            If m_bFinishCalled = True OrElse m_bCancelCalled = True Then
                ' reset flag to return control to default state
                'TODO: INSTANT VB TODO TASK: Assignments within expressions are not supported in VB.NET
                m_bFinishCalled = False
                m_bCancelCalled = False
                Return
            End If

            If btnCancel.Visible = True AndAlso btnCancel.Enabled = True Then
                Dim result As DialogResult = OnCancelPressed()

                ' if user select No in confirmation dialog then cancel closing process
                If result = DialogResult.No Then
                    e.Cancel = True
                End If
            End If
        End Sub

        Private Sub WizardForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
            AddHandler FindForm().KeyDown, AddressOf WizardForm_KeyDown
            AddHandler FindForm().Closing, AddressOf WizardForm_Closing

            ' make our NextFinish Button default to a form
            'this.FindForm().AcceptButton = btnNextFinish;
        End Sub
#End Region

        Private Sub lblDescription_Click(ByVal sender As Object, ByVal e As System.EventArgs)

        End Sub

    End Class
End Namespace
